# -*- coding: utf-8 -*-
"""
    xfree.core.changesets
    ~~~~~~~~~~~~~~~~~~~~~
    文件描述：核心接口，用于处理程序、服务等。
    作者：xfree
    邮箱：cy_83k@qq.com

"""

from abc import ABC, abstractmethod
from inspect import isclass

# 定义一个全局变量，用于存储EmptyValue的唯一实例
empty = None


class EmptyValue(object):
    """
    当None是一个可以应用于模型的有效值时，
    代表一个空的变更集值。

    这个类是一个单例。
    """

    __slots__ = ()  # 不需要额外的属性

    def __new__(cls):
        # 通过这个"hack"减少实例的数量
        global empty
        if empty is None:
            empty = super(EmptyValue, EmptyValue).__new__(cls)
        return empty

    def __eq__(self, other):
        # 检查other是否是EmptyValue类型或EmptyValue的子类
        return isinstance(other, EmptyValue) or (
            isclass(other) and issubclass(other, EmptyValue)
        )

    def __bool__(self):
        # 在布尔上下文中，EmptyValue总是被视为False
        return False

    __nonzero__ = __bool__  # Python 2兼容性


# 创建EmptyValue的唯一实例
empty = EmptyValue()


def is_empty(value, consider_none=False):
    """
    辅助函数，用于检查任意值是否是EmptyValue。
    如果consider_none为True，也会将None视为空值。
    """
    return empty == value or (consider_none and value is None)


class ChangeSetValidator(ABC):
    """
    用于验证变更集是否可以应用于模型的接口。
    """

    @abstractmethod
    def validate(self, model, changeset):
        """
        可能会抛出ValidationError异常，表示变更集不能应用于模型。
        或者抛出StopValidation异常，立即停止所有验证。
        """
        pass


class ChangeSetHandler(ABC):
    """
    用于将变更集应用于模型的接口。
    """

    @abstractmethod
    def apply_changeset(self, model, changeset):
        """
        接收当前模型和变更集对象，将变更集应用于模型并持久化模型。
        如果变更集无法应用，可能会抛出StopValidation异常。
        """
        pass


class ChangeSetPostProcessor(ABC):
    """
    用于处理变更集持久化后的动作的接口。
    """

    @abstractmethod
    def post_process_changeset(self, model, changeset):
        """
        用于响应变更集对模型的应用。
        """